{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Decision Tree"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* Você pode baixar o dataset em https://archive.ics.uci.edu/ml/datasets/Car+Evaluation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import os\n",
    "import subprocess\n",
    "import pandas as pd\n",
    "import math\n",
    "import numpy as np\n",
    "from sklearn.tree import DecisionTreeClassifier, export_graphviz"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "headers = [\"buying\", \"maint\", \"doors\", \"persons\",\"lug_boot\", \"safety\", \"class\"]\n",
    "data = pd.read_csv(\"carData.csv\", header=None, names=headers)\n",
    "\n",
    "data = data.take(np.random.permutation(len(data)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "No código acima, faremos a leitura do arquivo, informando que não há cabeçário (obrigatório) e a nossa coluna 6 (0-6) representa a label"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>buying</th>\n",
       "      <th>maint</th>\n",
       "      <th>doors</th>\n",
       "      <th>persons</th>\n",
       "      <th>lug_boot</th>\n",
       "      <th>safety</th>\n",
       "      <th>class</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>913</th>\n",
       "      <td>med</td>\n",
       "      <td>vhigh</td>\n",
       "      <td>3</td>\n",
       "      <td>more</td>\n",
       "      <td>med</td>\n",
       "      <td>med</td>\n",
       "      <td>acc</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1321</th>\n",
       "      <td>low</td>\n",
       "      <td>vhigh</td>\n",
       "      <td>2</td>\n",
       "      <td>more</td>\n",
       "      <td>big</td>\n",
       "      <td>med</td>\n",
       "      <td>acc</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>478</th>\n",
       "      <td>high</td>\n",
       "      <td>vhigh</td>\n",
       "      <td>3</td>\n",
       "      <td>more</td>\n",
       "      <td>small</td>\n",
       "      <td>med</td>\n",
       "      <td>unacc</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1389</th>\n",
       "      <td>low</td>\n",
       "      <td>vhigh</td>\n",
       "      <td>5more</td>\n",
       "      <td>4</td>\n",
       "      <td>med</td>\n",
       "      <td>low</td>\n",
       "      <td>unacc</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>581</th>\n",
       "      <td>high</td>\n",
       "      <td>high</td>\n",
       "      <td>3</td>\n",
       "      <td>4</td>\n",
       "      <td>med</td>\n",
       "      <td>high</td>\n",
       "      <td>acc</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     buying  maint  doors persons lug_boot safety  class\n",
       "913     med  vhigh      3    more      med    med    acc\n",
       "1321    low  vhigh      2    more      big    med    acc\n",
       "478    high  vhigh      3    more    small    med  unacc\n",
       "1389    low  vhigh  5more       4      med    low  unacc\n",
       "581    high   high      3       4      med   high    acc"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "buying      object\n",
       "maint       object\n",
       "doors       object\n",
       "persons     object\n",
       "lug_boot    object\n",
       "safety      object\n",
       "class       object\n",
       "dtype: object"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data.dtypes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "O problema é que nossos dados categóricos são strings. Então precisamos converter em representantes numéricos para aplicarmos no algoritmo"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>buying</th>\n",
       "      <th>maint</th>\n",
       "      <th>doors</th>\n",
       "      <th>persons</th>\n",
       "      <th>lug_boot</th>\n",
       "      <th>safety</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>class</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2</td>\n",
       "      <td>3</td>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>2</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1</td>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       buying  maint  doors  persons  lug_boot  safety\n",
       "class                                                 \n",
       "0           2      3      1        2         1       2\n",
       "0           1      3      0        2         0       2\n",
       "2           0      3      1        2         2       2\n",
       "2           1      3      3        1         1       1\n",
       "0           0      0      1        1         1       0"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "for h in headers:\n",
    "    data[h] = data[h].astype('category')\n",
    "    data[h] = data[h].cat.codes\n",
    "\n",
    "data.set_index(\"class\", inplace=True)\n",
    "data.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Faremos a separação dos dados em conjunto de treino e teste"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "size = len(data)\n",
    "trainSize = int(math.floor(size * 0.7))\n",
    "trainData = data[:trainSize]\n",
    "testData = data[trainSize:]\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Agora ok!\n",
    "Vamos ao que interessa..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DecisionTreeClassifier(class_weight=None, criterion='entropy', max_depth=None,\n",
       "            max_features=None, max_leaf_nodes=None, min_samples_leaf=1,\n",
       "            min_samples_split=2, min_weight_fraction_leaf=0.0,\n",
       "            presort=False, random_state=None, splitter='best')"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dTree = DecisionTreeClassifier(criterion=\"entropy\")\n",
    "dTree.fit(trainData.ix[:,0:6], trainData.index)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.96724470134874763"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dTree.predict(testData.ix[:, 0:6])\n",
    "dTree.score(testData.ix[:, 0:6], testData.index)\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "### Atividades\n",
    "\n",
    "1. Utilizamos a medida de Entropia como fator de decisão (medida de impureza de um nó). Teste o mesmo conjunto \n",
    "randômico de dados para a medida Gini e compare os resultados.\n",
    "Ref1.: http://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html#sklearn.tree.DecisionTreeClassifier\n",
    "Ref2.: https://en.wikipedia.org/wiki/Decision_tree_learning\n",
    "\n",
    "2. Aplique Decision Tree em outro dataset (link abaixo) e analise os resultados. Procure identificar (se há) relações entre as features (correlacionadas, por exemplo) e faça testes eliminando as que você achar desnecessárias, de forma a tentar melhorar seu classificador, seja em predição ou perfomance.\n",
    "Dataset: https://archive.ics.uci.edu/ml/datasets/Wine+Quality\n",
    "\n",
    "3. Execute a função abaixo para gerar a árvore que representa seu classificador (ambos utilizando entropia e gini como medidas). Analise a saida, entendendo como ela foi criada e os seus respectivos valores em relação a medida utilizada. Reflexão: seria possível construir nosso classificador apenas utilizando a estrutura condicional if-else?\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def visualize_tree(tree, feature_names):\n",
    "    \"\"\"Cria png que representa a arvore gerada.\n",
    "\n",
    "    Args\n",
    "    ----\n",
    "    tree -- DecsisionTree.\n",
    "    feature_names -- vetor com os nomes das features.\n",
    "    \"\"\"\n",
    "    with open(\"dt.dot\", 'w') as f:\n",
    "        export_graphviz(tree, out_file=f,\n",
    "                        feature_names=feature_names)\n",
    "\n",
    "    command = [\"dot\", \"-Tpng\", \"dt.dot\", \"-o\", \"dt.png\"]\n",
    "    try:\n",
    "        subprocess.check_call(command)\n",
    "    except:\n",
    "        exit(\"Nao foi possivel gerar a arvore.\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
